namespace BingMaps
{
    using System.Collections.Generic;
    using System.Reflection;
    using System.Windows;

    using ViewModel;

    using Funq;

    using GalaSoft.MvvmLight.Messaging;

    using WP7Contrib.Caching;
    using WP7Contrib.Common;
    using WP7Contrib.Communications;
    using WP7Contrib.Logging;
    using WP7Contrib.Messaging;
    using WP7Contrib.Serialization.Helpers;
    using WP7Contrib.Services.BingMaps;
    using WP7Contrib.Services.Location;
    using WP7Contrib.Services.Navigation;
    using WP7Contrib.Services.Settings;
    using WP7Contrib.Services.Storage;

    public class BootStrapper
    {
        #region Constants and Fields

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="BootStrapper"/> class.
        /// </summary>
        public BootStrapper()
        {
            this.Container = new Container();

            this.ConfigureContainer();
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets Container.
        /// </summary>
        public Container Container { get; private set; }

        #endregion

        #region Implemented Interfaces

        #region IDisposable

        /// <summary>
        /// The dispose.
        /// </summary>
        public void Dispose()
        {
            if (this.Container != null)
            {
                this.Container.Dispose();
                this.Container = null;
            }
        }

        #endregion

        #endregion

        #region Methods

        private void ConfigureContainer()
        {
            this.Container.Register<ILogManager>(c => new LoggingService("BingMaps"));
            this.Container.Register<ILog>(c => this.Container.Resolve<ILogManager>());

            var logManager = this.Container.Resolve<ILogManager>();
            logManager.Enable();

            this.Container.Register<IStoreSettings>(c => new SettingsStore(this.Container.Resolve<ILog>()));
            this.Container.Register<ISettings>(c => new Settings("AoAYqsmU8fmEynSb1ehNUnBPFLkTAIgDPrkk0ZymU8i_ZI-ZK6UE80zYgCyPiDwo", "EF79EAD2898E05B37E805F8547919DCA67154CBE", 5000, 10));

            var serialisationAssemblies = new List<Assembly> { this.GetType().Assembly, typeof(SerializeUri).Assembly };
            this.Container.Register<ICacheProvider>(c => new IsolatedStorageCacheProvider("BingMaps", serialisationAssemblies, c.Resolve<ILog>()));
            var cache = this.Container.Resolve<ICacheProvider>();
            System.Threading.ThreadPool.QueueUserWorkItem(state => cache.PreemptiveInitialise());

            this.Container.Register<IMessenger>(c => new LastMessageReplayMessenger());

            this.Container.Register<INavigationService>(c => new ApplicationFrameNavigationService(((App)Application.Current).RootFrame));

            this.Container.Register<INetworkService>(c => new NetworkMonitor(5000));

            var assemblies = new List<Assembly> { this.GetType().Assembly, typeof(BaseModel).Assembly };
            this.Container.Register<IStorageService>(c => new StorageService(assemblies, c.Resolve<ILog>()));

            this.Container.Register<IEncodeProperties>(c => new UrlEncoder());

            this.Container.Register<IHandleResourcesFactory>(c => new ResourceClientFactory(c.Resolve<ILog>()));

            this.Container.Register<IBingMapsService>(c => new BingMapsService(
                                                        c.Resolve<IHandleResourcesFactory>(),
                                                        c.Resolve<IEncodeProperties>(),
                                                        c.Resolve<ICacheProvider>(),
                                                        c.Resolve<ISettings>(),
                                                        c.Resolve<ILog>()));


            // LocationService:
            // 1. Registration
            this.Container.Register<ILocationService>(c => new LocationService(c.Resolve<ILog>()));

            this.Container.Register(
                c =>
                new MainViewModel(
                    c.Resolve<INavigationService>(),
                    c.Resolve<IMessenger>(),
                    c.Resolve<IStorageService>(),
                    c.Resolve<ILog>()));

            this.Container.Register(
                c =>
                new LocationViewModel(
                    c.Resolve<INavigationService>(),
                    c.Resolve<ILocationService>(),
                    c.Resolve<IBingMapsService>(),
                    c.Resolve<ILog>()));

            this.Container.Register(
                c =>
                new RouteViewModel(
                    c.Resolve<INavigationService>(),
                    c.Resolve<IBingMapsService>(),
                    c.Resolve<ILog>()));

            this.Container.Register(
                c =>
                new ImageryViewModel(
                    c.Resolve<INavigationService>(),
                    c.Resolve<IMessenger>(),
                    c.Resolve<ILocationService>(),
                    c.Resolve<IBingMapsService>(),
                    c.Resolve<ILog>()));

            this.Container.Register(
                c =>
                new SearchAreaViewModel(
                    c.Resolve<INavigationService>(),
                    c.Resolve<IMessenger>(),
                    c.Resolve<ILocationService>(),
                    c.Resolve<IBingMapsService>(),
                    c.Resolve<ILog>()));

            this.Container.Register(c => new SettingsViewModel());
        }

        #endregion
    }
}